<?php
/**
 * 移动文件或文件夹 - 支持批量（在原记录上执行更新操作）
 * 当有文件重名时，提示替换和保留两个文件
 * 当有文件夹重名时，提示跳过和保留两个文件夹
 *
 * @author Cyrano
 * @since 2018-03-08
 */
class Attachment_Move
{
    protected static $_res = array('status' => 0, 'msg' => '', 'data' => '');

    /**
     * 接口运行方法
     */
    public static function run($params)
    {
        $res = self::validate($params);
        if ($res['status'] == 0) {
            try {
                /* 检查目标目录是否存在 */
                $target_folder = array('_id' => 0, 'parent_id' => 0, 'hid' => '0');
                if ($res['data']['target_folder_fid'] > 0) {
                    $target_folder = Attachment_Model_Folder::instance()->getFolderByFid($res['data']['userid'], $res['data']['target_folder_fid']);
                    if (empty($target_folder) || $target_folder[0]['status'] != 1) {
                        throw new Exception('您要移动到的目标目录不存在');
                    }
                    $target_folder = $target_folder[0];
                }

                /* 逐个分析文件夹 */
                $data_exsit = array();
                if ($res['data']['folders']) {
                    $folders = Attachment_Model_Folder::instance()->getFolderByFid($res['data']['userid'], $res['data']['folders']);
                    if (! empty($folders)) {
                        foreach ($folders as $k => $v) {
                            /* 不能将文件移动到自身或其子目录下 */
                            if ($v['parent_id'] == $target_folder['fid'] || false !== strpos($target_folder['hid'], $v['hid'])) {
                                throw new Exception('不能将文件移动到自身或其子目录下');
                                break;
                            }

                            /* 判断是否强制移动 */
                            if (isset($params['is_force']) && $params['is_force'] == 1) {
                                self::_moveFolder($v, $target_folder);
                            } else {
                                /* 执行分析 */
                                $where_exsit = array(
                                    'userid' => $res['data']['userid'],
                                    'parent_id' => $target_folder['fid'],
                                    'title' => $v['title'],
                                    'status' => 1
                                );
                                $target_exsit = Attachment_Model_Folder::instance()->fetchByWhere($where_exsit);
                                if (! empty($target_exsit)) {
                                    /* 已存在，汇总提示 */
                                    $data_exsit[] = array(
                                        'type' => 'folder',
                                        'title' => $target_exsit[0]['title'],
                                        'existent' => array(
                                            '_id' => $target_exsit[0]['_id'],
                                            'fid' => $target_exsit[0]['fid'],
                                            'mtime' => Util_Timer::formatMicrotime($target_exsit[0]['mtime'], 'Y-m-d H:i')
                                        ),
                                        'tomove' => array(
                                            '_id' => $v['_id'],
                                            'fid' => $v['fid'],
                                            'mtime' => Util_Timer::formatMicrotime($v['mtime'], 'Y-m-d H:i')
                                        )
                                    );
                                } else {
                                    /* 不存在，执行移动 */
                                    self::_moveFolder($v, $target_folder);
                                }
                            }
                        }
                    }
                }

                /* 逐个分析文件 */
                if ($res['data']['attachments']) {
                    $attachments = Attachment_Model_Content::instance()->fetchByPK($res['data']['attachments']);
                    if (! empty($attachments)) {
                        foreach ($attachments as $k => $v) {
                            /* 不能将文件移动到自身或其子目录下 */
                            if ($v['folder_hid'] == $target_folder['hid']) {
                                throw new Exception('不能将文件移动到自身或其子目录下');
                                break;
                            }

                            /* 判断是否强制移动 */
                            if (isset($params['is_force']) && $params['is_force'] == 1) {
                                self::_moveFile($v, $target_folder);
                            } else {
                                /* 执行分析 */
                                $where_exsit = array(
                                    'userid' => $res['data']['userid'],
                                    'title' => $v['title'],
                                    'folder_hid' => $target_folder['hid'],
                                    'status' => 1
                                );
                                $target_exsit = Attachment_Model_Content::instance()->fetchByWhere($where_exsit);
                                if (!empty($target_exsit)) {
                                    /* 已存在，汇总提示 */
                                    $data_exsit[] = array(
                                        'type' => 'file',
                                        'title' => $target_exsit[0]['title'],
                                        'existent' => array(
                                            '_id' => $target_exsit[0]['_id'],
                                            'filesize' => $target_exsit[0]['filesize'] / 1000,
                                            'mtime' => Util_Timer::formatMicrotime($target_exsit[0]['mtime'], 'Y-m-d H:i')
                                        ),
                                        'tomove' => array(
                                            '_id' => $v['_id'],
                                            'filesize' => $v['filesize'] / 1000,
                                            'mtime' => Util_Timer::formatMicrotime($v['mtime'], 'Y-m-d H:i')
                                        )
                                    );
                                } else {
                                    /* 不存在，执行移动 */
                                    self::_moveFile($v, $target_folder);
                                }
                            }
                        }
                    }
                }

                /* 合并分析结果 */
                $data = ! empty($data_exsit) ? $data_exsit : '';

                $res['data'] = $data;
            } catch (Exception $e) {
                $res['status'] = 1;
                $res['msg'] = '移动失败。错误信息：' . $e->getMessage();
                $res['data'] = '';
            }
        }

        return $res;
    }

    /**
     * 验证参数
     */
    private static function validate($params)
    {
        try {
            /* 校验参数 */
            if (! isset($params['userid']) || ! $params['userid']) {
                throw new Exception('参数 userid 未提供');
            }
            if (! isset($params['folders']) || ! $params['folders']) {
                $params['folders'] = '';
            }
            if (! isset($params['attachments']) || ! $params['attachments']) {
                $params['attachments'] = '';
            }

            /* 处理要移动到的目标目录 */
            if (! isset($params['target_folder_fid']) || ! $params['target_folder_fid']) {
                $params['target_folder_fid'] = 0;
            }

            self::$_res['data'] = $params;
        } catch (Exception $e) {
            self::$_res['status'] = 1;
            self::$_res['msg'] = $e->getMessage();
        }

        return self::$_res;
    }

    /**
     * 移动文件
     *
     * @param array $info 要移动的文件信息
     * @param array $target_folder 目标目录信息
     */
    private static function _moveFile($info, $target_folder)
    {
        /* 处理要更新的数据 */
        $set_update = array(
            'folder_hid' => $target_folder['hid'],
            'mtime' => Util_Timer::getMicrotime()
        );

        /* 更新 */
        Attachment_Model_Content::instance()->updateForEntity($set_update, $info['_id']);

        /* 更新文件（夹）同名处理表 */
        Attachment_Juna::updateCopyNums($info['userid'], $info['title'], 1, $target_folder['hid']);
    }

    /**
     * 移动文件夹
     *
     * @param array $info 要移动的文件夹信息
     * @param array $target_folder 目标目录信息
     */
    private static function _moveFolder($info, $target_folder)
    {
        /* 移动文件夹 */
        $set = self::_moveFolderUpdate($info, $target_folder);

        /* 递归移动文件夹下的子级文件及文件夹 */
        if ($info['is_has_children'] == 1) {
            self::_moveFolderChildrenDir($info, $set);
            self::_moveFolderChildrenFile($info, $set);
        }
    }

    /**
     * 递归移动指定文件夹下的子级文件夹
     *
     * @param array $info 要移动的文件夹信息
     * @param array $target_folder 目标目录信息
     */
    private static function _moveFolderChildrenDir($info, $target_folder)
    {
        /* 查询要移动的文件夹下的子级文件夹信息并移动 */
        $where = array('parent_id' => $info['fid'], 'userid' => $info['userid']);
        $folders = Attachment_Model_Folder::instance()->fetchByWhere($where);
        if (! empty($folders)) {
            foreach ($folders as $k => $v) {
                $set = self::_moveFolderUpdate($v, $target_folder);
                if ($v['is_has_children'] == 1) {
                    self::_moveFolderChildrenDir($v, $set);
                    self::_moveFolderChildrenFile($v, $set);
                }
            }
        }
    }

    /**
     * 递归移动指定文件夹下的子级文件
     *
     * @param array $info 要移动的文件夹信息
     * @param array $target_folder 目标目录信息
     */
    private static function _moveFolderChildrenFile($info, $target_folder)
    {
        /* 查询要移动的文件夹下的子级文件信息并移动 */
        $where = array('userid' => $info['userid'], 'folder_hid' => $info['hid']);
        $files = Attachment_Model_Content::instance()->fetchByWhere($where);
        if (! empty($files)) {
            foreach ($files as $k => $v) {
                self::_moveFile($v, $target_folder);
            }
        }
    }

    /**
     * 移动文件夹 - 执行更新
     *
     * @param array $info 要移动的文件夹信息
     * @param array $target_folder 目标目录信息
     */
    private static function _moveFolderUpdate($info, $target_folder)
    {
        /* 处理要更新的数据 */
        $set_update = array(
            'parent_id' => $target_folder['fid'],
            'hid' => $target_folder['hid'] . ':' . str_pad($info['fid'], 5, 0, STR_PAD_LEFT),
            'mtime' => Util_Timer::getMicrotime()
        );

        /* 执行更新 */
        Attachment_Model_Folder::instance()->updateForEntity($set_update, $info['_id']);

        /* 更新文件（夹）同名处理表 */
        Attachment_Juna::updateCopyNums($info['userid'], $info['title'], 2, $target_folder['hid']);

        /* 处理返回数据 */
        $data = array_merge($info, $set_update);

        return $data;
    }
}
